#include <stdio.h>
#include <getopt.h>
#include <signal.h>

#include "../system/proc.h"
#include "../system/game.h"
#include "system/sinet.h"

extern snake_t players[MAX_PLAYERS];
extern uint16_t num_clients;
extern fd_set master;
extern int max_fd;
extern uint16_t alive_snakes;
extern FILE* log_file;


void HUI(int hui)
{
    fprintf(stderr, "HUI\n");
}

//TODO: add fruit
int main(int argc, char *argv[])
{
    signal(SIGHUP, HUI);

    int8_t ret;
    uint16_t port = 2229;
    uint16_t field_size_x = 80;
    uint16_t field_size_y = 20;
    uint16_t frame_delay = 300;
    struct timespec time_stamp;
    time_stamp.tv_sec = 1;
    time_stamp.tv_nsec = 0;
    log_file = stdin;

    struct sockaddr_in addr;
    struct timespec timest = {0};
    struct timespec fr_d;

    fd_set read_fds;

    while ((ret = getopt(argc, argv, "hp:x:y:d:t:n:f:")) != -1) 
    {
        switch (ret)
        {
            case 'p':
                port = atoi(optarg);
            break;

            case 'h':
                printf("%s", HELP_SERVER);
                exit(EXIT_SUCCESS);
            break;
        
            case 'x':
                field_size_x = atoi(optarg);
            break;

            case 'y':
                field_size_y = atoi(optarg);
            break;

            case 'd':
                frame_delay = atoi(optarg);
            break;

            case 't':
                time_stamp.tv_sec = atoi(optarg);
            break;

            case 'n':
                num_clients = atoi(optarg);
            break;

            case 'f':
                log_file = fopen(optarg, "w");
         }
    }  
    
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = INADDR_ANY;
    addr.sin_port = htons(port);

    srand((unsigned)time(0x0));
    init_server(&addr);
    wait_clients();
    gen_snakes(field_size_x, field_size_y);

    clock_gettime(CLOCK_REALTIME, &timest);
    timest.tv_sec += time_stamp.tv_sec;

    send_init_mess(&timest, frame_delay, field_size_x, field_size_y);
    send_init_fruit(field_size_x, field_size_y);

    clock_gettime(CLOCK_REALTIME, &time_stamp);
    timest = timespec_subtract(time_stamp, timest);
    nanosleep(&timest, NULL);

    fr_d.tv_nsec += frame_delay * 1000000;
    fr_d.tv_sec = 0;
    
    while(true)
    {
        FD_ZERO(&read_fds);
        read_fds = master;
        Pselect(max_fd+1, &read_fds, &fr_d);

        uint8_t flag;
        for (int fd = 0; fd < max_fd+1; ++fd)
        {
            if (FD_ISSET(fd, &read_fds))
            {
                flag = Recv(fd, &players[fd2num(fd)].dir, 1, 0);
                if (flag == 0)
                    dead(fd2num(fd));
            }
        }
        
        for (int i = 0; i < num_clients; ++i)
        {
            if (check_eat(i))
            {
                spawn_fruit(field_size_x, field_size_y);
                send_fruit();
            }
        }

        change_crd_snakes();
        
        for (int i = 0; i < num_clients; ++i)
        {
            if (check_dead(i, field_size_x, field_size_y))
                dead(i);
        }

        if (alive_snakes == 0)
            exit(EXIT_SUCCESS);        

        send_snakes();
    }
}
